/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */
package com.pig4cloud.pigx.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.customize.enums.AbnormalEnum;
import com.pig4cloud.pigx.common.customize.exception.DuckweedException;
import com.pig4cloud.pigx.common.customize.mysql.utils.MysqlUtil;
import com.pig4cloud.pigx.common.customize.security.utils.SecurityUtil;
import com.pig4cloud.pigx.common.customize.utils.id.IdWorker;
import com.pig4cloud.pigx.common.security.service.PigxUser;
import com.pig4cloud.pigx.user.dto.AppRechargeRecordPageDTO;
import com.pig4cloud.pigx.user.dto.RechargeRecordPageDTO;
import com.pig4cloud.pigx.user.dto.UpdateCapitalAccountDTO;
import com.pig4cloud.pigx.user.entity.CapitalAccount;
import com.pig4cloud.pigx.user.entity.RechargeRecord;
import com.pig4cloud.pigx.user.entity.User;
import com.pig4cloud.pigx.user.enums.RechargeRecordEnum;
import com.pig4cloud.pigx.user.mapper.RechargeRecordMapper;
import com.pig4cloud.pigx.user.service.RechargeRecordService;
import com.pig4cloud.pigx.user.vo.AdminPageDemoVO;
import com.pig4cloud.pigx.user.vo.AppRechargeRecordPageVO;
import com.pig4cloud.pigx.user.vo.RechargeRecordPageVO;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 充值记录
 *
 * @author pigx code generator
 * @date 2022-11-21 16:43:06
 */
@Service
@AllArgsConstructor
public class RechargeRecordServiceImpl extends ServiceImpl<RechargeRecordMapper, RechargeRecord> implements RechargeRecordService {

	private final MysqlUtil mysqlUtil;

	private final IdWorker idWorker;

	@Override
	public R<AdminPageDemoVO<RechargeRecordPageVO>> voPage(RechargeRecordPageDTO dto) {
		try {
			QueryWrapper<RechargeRecord> wrapper = new QueryWrapper<RechargeRecord>() {{
				if (dto.getUserId() != null) {
					like("user_id", dto.getUserId());
				}
				if (dto.getType() != null && !dto.getType().isEmpty()) {
					eq("type", dto.getType());
				} else {
					in("type", RechargeRecordEnum.Type.CHAIN_RECHARGE.getValue(), RechargeRecordEnum.Type.USER_RECHARGE.getValue());
				}
				if (dto.getState() != null && !dto.getState().isEmpty()) {
					eq("state", dto.getState());
				}
				if (dto.getChain() != null && !dto.getChain().isEmpty()) {
					eq("public_chain",dto.getChain());
				}
				if (dto.getTransactionHash() != null && !dto.getTransactionHash().isEmpty()) {
					like("transaction_hash",dto.getTransactionHash());
				}
				if (dto.getStartTime() != null) {
					ge("create_time", dto.getStartTime());
				}
				if (dto.getEndTime() != null) {
					le("create_time", dto.getEndTime());
				}
				orderByDesc("create_time");
			}};
			// 列表分页
			Page<RechargeRecord> page = baseMapper.selectPage(new Page<RechargeRecord>() {{
				setCurrent(dto.getCurrent());
				setSize(dto.getSize());
			}}, wrapper);
			List<RechargeRecordPageVO> list = new ArrayList<>();
			for (RechargeRecord record : page.getRecords()) {
				RechargeRecordPageVO vo = new RechargeRecordPageVO();
				BeanUtils.copyProperties(record,vo);
				vo.setType(RechargeRecordEnum.Type.findName(vo.getType()));
				vo.setState(RechargeRecordEnum.Status.findName(vo.getState()));
				list.add(vo);
			}
			Page<RechargeRecordPageVO> voPage = new Page<>();
			BeanUtils.copyProperties(page,voPage);
			voPage.setRecords(list);
			// 数据统计
			RechargeRecord record = baseMapper.selectOne(wrapper.select(
					"sum(quantity) 'quantity'"
			));
			RechargeRecordPageVO vo = new RechargeRecordPageVO();
			if (record != null) {
				BeanUtils.copyProperties(record,vo);
			}
			return R.ok(new AdminPageDemoVO<RechargeRecordPageVO>(){{
				setPage(voPage);
				setStatistics(vo);
			}});
		} catch (Exception e) {
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}

	@Override
	public R<Page<AppRechargeRecordPageVO>> getListByApp(AppRechargeRecordPageDTO dto) {
		try {
			PigxUser user = SecurityUtil.getLoginUser();
			if (user == null) {
				throw new DuckweedException(AbnormalEnum.MSG.OPTIONS_USER_NOT_FOUND);
			}
			Page<RechargeRecord> page = baseMapper.selectPage(new Page<RechargeRecord>() {{
				setCurrent(dto.getCurrent());
				setSize(dto.getSize());
			}}, new QueryWrapper<RechargeRecord>() {{
				eq("user_id",user.getId());
				if (dto.getState() != null) {
					eq("state", dto.getState());
				}
				in("type",RechargeRecordEnum.Type.CHAIN_RECHARGE.getValue(),RechargeRecordEnum.Type.USER_RECHARGE.getValue());
				if (dto.getStartTime() != null) {
					ge("create_time", dto.getStartTime());
				}
				if (dto.getEndTime() != null) {
					le("create_time", dto.getEndTime());
				}
				orderByDesc("create_time");
			}});
			Page<AppRechargeRecordPageVO> voPage = new Page<>();
			BeanUtils.copyProperties(page,voPage);
			List<AppRechargeRecordPageVO> voList = new ArrayList<>();
			for (RechargeRecord record : page.getRecords()) {
				AppRechargeRecordPageVO vo = new AppRechargeRecordPageVO();
				BeanUtils.copyProperties(record,vo);
				vo.setType(RechargeRecordEnum.Type.findName(vo.getType()));
				vo.setState(RechargeRecordEnum.Status.findName(vo.getState()));
				voList.add(vo);
			}
			voPage.setRecords(voList);
			return R.ok(voPage);
		} catch (DuckweedException e) {
			throw e;
		} catch (Exception e) {
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}

	/**
	 * 人工充值
	 */
	@Override
	public R<String> userRecharge(UpdateCapitalAccountDTO dto) {
		if (dto.getUserId() == null) {
			throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"充值用户ID不能为空");
		}
		User user = new User().selectById(dto.getUserId());
		if (user == null) {
			throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"找不到该用户,请检查用户ID填写是否正确");
		}
		if (dto.getBalance() == null) {
			throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"充值数量不能为空");
		}
		if (dto.getBalance().compareTo(BigDecimal.ZERO) <= 0) {
			throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"充值数量不能小于0");
		}
		if (dto.getRemark() == null || dto.getRemark().isEmpty()) {
			throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"人工充值必须填写备注");
		}
		try {
			mysqlUtil.startLocalTx();
			CapitalAccount one = new CapitalAccount().selectOne(new QueryWrapper<CapitalAccount>() {{
				eq("user_id", dto.getUserId());
				last("for update");
			}});
			if (one == null) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"用户资金账户不存在");
			}
			// 账户数量变更
			one.setBalance(one.getBalance().add(dto.getBalance()));
			one.updateById();
			// 增加充值记录
			baseMapper.insert(new RechargeRecord(){{
				setId(idWorker.nextId());
				setUserId(one.getUserId());
				// 人工充值
				setType(RechargeRecordEnum.Type.USER_RECHARGE.getValue());
				setQuantity(dto.getBalance());
				// 已完成
				setState(RechargeRecordEnum.Status.SUCCESS.getValue());
				setCurrency(one.getCurrency());
				// 备注
				setRemark(dto.getRemark());
			}});
			mysqlUtil.commitLocalTx();
			return R.ok("充值成功");
		} catch (Exception e) {
			mysqlUtil.rollbackLocalTx();
			return R.failed("系统异常,充值失败");
		}
	}

}
